#include "Output.hpp"

#include "Expression.hpp"
#include "ExpressionValue.hpp"

#include "CallingInstance.hpp"
#include "ProgramManager.hpp"
#include "Memory.hpp"

#include <iostream>
#include <iomanip>

Output::Output ( std::vector < Expression* > toDisplay )
{
    for ( unsigned int i = 0 ; i < toDisplay.size () ; ++ i )
        _toManage.push_back ( toDisplay [ i ] );
    toDisplay.clear ();
}

Output::~Output ()
{
}

void
Output::execute ()
{
    int vinteger;
    float vreal;
    bool vboolean;
    unsigned int vaddress;
    LOGFUNCTION ( IEXEC_LOG );
    for ( unsigned int i = 0 ; i < _toManage.size () ; ++ i )
    {
        _toManage [ i ]->compute ();
        ExpressionValue value = _toManage [ i ]->getValue ();
//        std::cout << "(" << value._type._base << "," << value._type._modifier << "," << value._type._size << ") ";
        if ( value._class == CE_VALUE )
        {
            switch ( value._type._modifier )
            {
            case NONE:
                switch ( value._type._base )
                {
                case INTEGER:
                    std::cout << value._value._vinteger;
                    break;
                case REAL:
                    std::cout << value._value._vreal;
                    break;
                case BOOLEAN:
                    std::cout << ( value._value._vboolean ? "true" : "false" );
                    break;
                case STRING:
                    std::cout << value._value._vstring;
                    break;
                default:
                    break;
                }
                break;
            case POINTER:
                if ( value._type._base != STRING )
                {
                    std::cout << value._value._vaddress;
                }
                break;
            case ARRAY:
                break;
            default:
                break;
            }
        }
        else if ( value._class == CE_MEMORY )
        {
            CallingInstance* instance = ProgramManager::getCurrentInstance ();
            Memory* memoire = instance->getMemory ();
            switch ( value._type._modifier )
            {
            case NONE:
                switch ( value._type._base )
                {
                case INTEGER:
                    memoire->get ( value._value._vaddress, (void*) & vinteger, getTypeSize ( value._type ) );
                    std::cout << vinteger;
                    break;
                case REAL:
                    memoire->get ( value._value._vaddress, (void*) & vreal, getTypeSize ( value._type ) );
                    std::cout << vreal;
                    break;
                case BOOLEAN:
                    memoire->get ( value._value._vaddress, (void*) & vboolean, getTypeSize ( value._type ) );
                    std::cout << ( vboolean ? "true" : "false" );
                    break;
                case STRING:
                    break;
                default:
                    break;
                }
                break;
            case POINTER:
                if ( value._type._base != STRING )
                {
                    memoire->get ( value._value._vaddress, (void*) & vaddress, getTypeSize ( value._type ) );
                    std::cout << vaddress;
                }
                break;
            case ARRAY:
                break;
            default:
                break;
            }
        }
    }
}

void
Output::display ( const unsigned int shift ) const
{
    std::cout << "write ( ";
    for ( unsigned int i = 0 ; i < _toManage.size () ; ++ i )
    {
        _toManage [ i ]->display ( shift );
        if ( i < _toManage.size () - 1 )
            std::cout << ", ";
    }
    std::cout << " )";
}

